package graph_viewer.factory;

import java.io.*;
import java.util.*;
//import java.io.IOException;

import org.w3c.dom.*;
import org.xml.sax.*;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;

import graph_viewer.structure.*;
import graph_viewer.structure.builder.*;
import graph_viewer.app_exception.*;
import graph_viewer.util.*;

/**
	parse xml source file, return an instance of  Citation_Graph
*/
public class  Citation_Graph_Factory{	
	static public void main( String[] args ) throws IOException{
		Citation_Graph_Factory cgf	= new Citation_Graph_Factory();
		

		//Citation_Graph a_citation_graph = cgf.create();

		//Debug.println( a_citation_graph.toString(), 56 );

		cgf.generate_gvr_file();
	}


	static String
		xml_file	= "d:\\project\\graph_viewer\\sample_reference.xml",
						//"d:\\project\\graph_viewer\\book-order.xml";
		topic_file	 = "d:\\project\\graph_viewer\\classify_result.txt";

	
	public Citation_Graph_Factory(){}

	public Citation_Graph create(){		
		ArrayList 
			node_list		= build_nodes(),//parse_nodes(),
			edge_list	= build_edges( node_list );


		Citation_Graph a_citation_graph	= new Citation_Graph( node_list, edge_list );

		return a_citation_graph;
	}

	/**
	Sample of App Format file:
	sample.gvr

	[node]
	0,ECperfBeans
	1,mfg
	2,supplier
	1_1,LargeOrderSes
	1_2,WorkOrderSes
	2_1,BuyerSes
	2_2,ReceiverSes
	2_3,SupplierEnt

	[relation]
	#	node	parent
	0,-
	1,0
	2,0
	1_1,1
	1_2,1
	2_1,2
	2_2,2
	2_3,2

	[edge]
	#	from,to
	1_1,1_2
	1_2,2_1

	~

	*/
	public void generate_gvr_file() throws IOException{
		String file_name	= "ieee.gvr";
		
		generate_node_info( file_name );
		File_Util.append_to_file( file_name,  "\n" );

		generat_relation_info( file_name );
		File_Util.append_to_file( file_name,  "\n" );

		generate_edge_info( file_name );
		File_Util.append_to_file( file_name,  "\n" );


		File_Util.append_to_file( file_name,  "~" );

	}
	
	private void generate_edge_info( String file_name ) throws IOException{
		File_Util.append_to_file( file_name,  "[edge]" );

		ArrayList edges	= build_edges(  build_nodes() );

		for ( Iterator _i = edges.iterator(); _i.hasNext(); ){
			String an_edge	= (String)_i.next();
		
			File_Util.append_to_file( file_name,  an_edge );
		}
	}

	private void  generat_relation_info( String file_name ) throws IOException{
		File_Util.append_to_file( file_name,  "[relation]" );
		File_Util.append_to_file( file_name,  "0,-" );

		generate_super_cluster_relation_info( file_name );
		generate_paper_relation_info( file_name );
	}

	private void generate_super_cluster_relation_info( String file_name ) throws IOException{
		for ( int topic_loop = 1; topic_loop <=11; topic_loop++){

			File_Util.append_to_file( file_name,  topic_loop + ",0" );

			for ( int year_loop = IEEE_Infovis_Paper.START_YEAR;
					year_loop <= IEEE_Infovis_Paper.END_YEAR; 
					year_loop ++ )
			{
				//2_1995, 2
				File_Util.append_to_file( file_name,  topic_loop + "_" + year_loop + ", " + topic_loop );	 	
			}
		}		
	}
	
	private void generate_paper_relation_info( String file_name ) throws IOException{
		ArrayList node_list		= build_nodes();

		for ( Iterator _i = node_list.iterator(); _i.hasNext(); ){
			IEEE_Infovis_Paper a_paper	= (IEEE_Infovis_Paper)_i.next();

			String
				id		= a_paper.get_id(),
				topic	= a_paper.get_topic(),
				year		= a_paper.get_year();
			//acm123456, 2_1995
			File_Util.append_to_file( file_name,  id + "," + topic + "_" + year );	
		}
		
	}


	private void generate_node_info( String file_name ) throws IOException{
		File_Util.append_to_file( file_name,  "[node]" );
		File_Util.append_to_file( file_name,  "0, IEEE citations" );

		generate_super_clusters_info( file_name );
		generate_paper_nodes_info( file_name );
	}
	//11 topics
	//1995-2002
	private void generate_super_clusters_info( String file_name ) throws IOException{
		for ( int i = 1; i <= IEEE_Infovis_Paper.TOPICS.length; i++ ){
			File_Util.append_to_file( file_name,  i + "," + IEEE_Infovis_Paper.TOPICS[i -1] );
			
			for ( int j = IEEE_Infovis_Paper.START_YEAR; j <=IEEE_Infovis_Paper.END_YEAR; j++){				
					File_Util.append_to_file( file_name,  i + "_" + j + ", " + j );
			}
		}				
	}
	
	//
	private void generate_paper_nodes_info( String file_name ) throws IOException{	
		ArrayList node_list		= build_nodes();

		for ( Iterator _i = node_list.iterator(); _i.hasNext(); ){
			IEEE_Infovis_Paper a_paper	= (IEEE_Infovis_Paper)_i.next();

			String artical_id	= a_paper.get_id();						
			File_Util.append_to_file( file_name,  artical_id + ", " + artical_id );
		}
	}

//==============================================================//
	private ArrayList build_edges( ArrayList paper_list ){
		ArrayList edge_list	= new ArrayList( );

		for ( Iterator _i = paper_list.iterator(); _i.hasNext(); ){
			IEEE_Infovis_Paper a_paper_node = (IEEE_Infovis_Paper)_i.next();
			String a_paper_id	 = a_paper_node.get_id();

			ArrayList references	= a_paper_node.get_references();

			for ( Iterator _j = references.iterator(); _j.hasNext(); ){
				String a_ref	 = (String)_j.next();

				for ( Iterator _k =  paper_list.iterator(); _k.hasNext() ; ){
					IEEE_Infovis_Paper a_paper_node_cp = (IEEE_Infovis_Paper)_k.next();
					String a_paper_cp_id	= a_paper_node_cp.get_id();

					if ( a_paper_cp_id.equals(a_ref ) ){
						edge_list.add( a_paper_id + "," + a_paper_cp_id );
					}
				}
			}
		}

		return edge_list;
	}

	private ArrayList parse_nodes(){
		ArrayList node_list	= new ArrayList();

		ArrayList data_lines	= File_Util.read_file(xml_file);

		int size	= data_lines.size();

		for ( int i = 0; i < size; i++ ){
			String a_line	= (String)data_lines.get( i );
			String net_line	= a_line.trim();
			
			if ( a_line.trim().startsWith( "<article id=" ) ){
				ArrayList a_paper = new ArrayList();

				//Debug.println( "\n===========A new paper===========\n" , 56 );
								
				int j = i;

				for ( ; j < size ; j ++ ){
					String a_paper_line	=(String)data_lines.get( j );
					
					net_line = a_paper_line.trim();
					
					if ( net_line.startsWith( "</article" ) ){
						break;
					}
					if ( is_wanted_tag( net_line ) ){
						a_paper.add( net_line );
					}
				} //end for j
				
				i = j;

				//Debug.println( a_paper.toString() , 56 );
				IEEE_Infovis_Paper a_paper_node = create_paper( a_paper );
				//Debug.println( "" + a_paper_node, 56 );
				
				if ( is_infovis_source( a_paper_node.get_source() ) ){
					node_list.add( a_paper_node );
				}

				
			}//end if

		}// end for i

		return node_list;
	}
	
	private ArrayList build_nodes(){		
		ArrayList node_list	= parse_nodes();

		ArrayList topic_lines	= File_Util.read_file(topic_file);

		for ( Iterator _i = topic_lines.iterator(); _i.hasNext(); ){
			String a_line	= (String)_i.next();
			String a_topic_line	= a_line.trim();

			if ( a_topic_line.length() == 0 ){
				continue;
			}
			//11 acm540298 Clustering Algorithms, 99th edition
			//Debug.println( a_topic_line + "\n", 56);
			StringTokenizer st = new StringTokenizer( a_topic_line, " ");

			ArrayList topic_fields	= new ArrayList();
			
			while (st.hasMoreTokens()) {
				topic_fields.add(st.nextToken());
			}

			String
				topic		= (String)topic_fields.get(0),
				artical_id	= (String)topic_fields.get(1);
			//Debug.println( "topic:" + topic + ", attical_id" + artical_id, 56 );

			for ( Iterator _j = node_list.iterator(); _j.hasNext(); ){
				IEEE_Infovis_Paper a_paper_node = (IEEE_Infovis_Paper)_j.next();

				if ( artical_id. equals( a_paper_node.get_id() ) ){
					a_paper_node.set_topic( topic );
				}
			}

		}
		
		for ( Iterator _i = node_list.iterator(); _i.hasNext(); ){
			IEEE_Infovis_Paper a_paper	= (IEEE_Infovis_Paper)_i.next();
			String topic	= a_paper.get_topic();

			if ( topic.trim().length() == 0 ){
				a_paper.set_topic( "1" );

			}
		}
		return node_list;
	}
	private boolean is_wanted_tag (String a_line ){
		String a_net_line	= a_line.trim();
		boolean
			is_artical_id	= a_net_line.startsWith( "<article"),
			is_title		= a_net_line.startsWith( "<title" ),
			is_author	= a_net_line.startsWith( "<author_ref" ),
			is_ref		= a_net_line.startsWith( "<ref ref=" ),
			is_conference_source	= a_net_line.startsWith( "<source ref" ),
			is_date		= a_net_line.startsWith( "<date from=" );

		return is_artical_id 
				|| is_title
				|| is_author
				|| is_date 
				|| is_conference_source
				|| is_ref ;
	}
	
	//@param a_paper_information an arraylist contains complete information of a paper node.
	private IEEE_Infovis_Paper create_paper( ArrayList a_paper_information ){		
		IEEE_Infovis_Paper a_paper		= new IEEE_Infovis_Paper();

		for ( Iterator _i = a_paper_information.iterator(); _i.hasNext(); ){
			String
				a_line		= (String)_i.next(),
				a_net_line	= a_line.trim();
			
			if ( a_net_line.startsWith( "<article" ) ){
				String article_id	= find_artical_id( a_net_line );
				a_paper.set_id( article_id );
			}else if ( a_net_line.startsWith( "<title"  )  ){
				String title	= find_title( a_net_line );
				a_paper.set_title( title );
			}else if( a_net_line.startsWith( "<source ref"  )  ){
				String source	= find_source( a_net_line );

				a_paper.set_source( source );
			}else if ( a_net_line.startsWith( "<date from="  )  ){
				String date	= find_date( a_net_line );
				a_paper.set_year( date );
			}else if ( a_net_line.startsWith( "<author_ref ref="  )  ){
				String author	= find_author( a_net_line );
				a_paper.add_an_author( author );
			}else if( a_net_line.startsWith( "<ref ref="  )  ){
				String ref	= find_ref( a_net_line );
				a_paper.add_a_reference( ref );
			}
		}

		return a_paper;
	}

	//@param a_net_line <article id="acm721078">
	private String find_artical_id( String a_net_line ){
		String artical_id = new String();
		
		int
			index_first_quota	= a_net_line.indexOf( "\"" ),
			index_last_quota	= a_net_line.lastIndexOf( "\"" );
		
		artical_id = a_net_line.substring( index_first_quota + 1, index_last_quota);

		return artical_id;
	}
	
	//@param a_net_line <title>An Operator Interaction Framework for Visualization Systems</title>
	private String find_title( String a_net_line ){
		String title	= new String();

		int 
			index_first_right_closet	= a_net_line.indexOf( ">" ),
			index_second_left_closet	= a_net_line.lastIndexOf( "<" );

		title	= a_net_line.substring( index_first_right_closet + 1, index_second_left_closet );
		
		return title;
	}

	//@param a_net_line <author_ref ref="P74503">Ed Huai-hsin Chi</author_ref>
	private String find_author( String a_net_line ){
		String author	= new String();
		
		int 
			index_first_right_closet	= a_net_line.indexOf( ">" ),
			index_second_left_closet	= a_net_line.lastIndexOf( "<" );

		author	= a_net_line.substring( index_first_right_closet + 1, index_second_left_closet );

		return author;
	}

	//@param a_net_line <date from="10-19-1998" to="10-20-1998"/>	
	private String find_date( String a_net_line ){
		String year	= new String();
				
		int 
			index_last_dash	= a_net_line.lastIndexOf( "-" ),
			index_last_quota	= a_net_line.lastIndexOf( "\"" );
		
		year		= a_net_line.substring( index_last_dash + 1, index_last_quota );
		
		//<date from="2000
		if ( year.startsWith( "<date from=" ) ){
			int index_first_quota = year.indexOf( "\"" );
			year = year.substring( index_first_quota + 1, year.length() );
		}

		return year;
	}
	
	//@param a_net_line <ref ref="acm37086">R. A. Becker and W. S. Cleveland. "Brushing scatterplots". Technometrics, 29(2):127-142, 1987.</ref>
	private String find_ref( String a_net_line ){
		String ref	 = new String();

		int 
			index_first_quota			= a_net_line.indexOf( "\"" ),
			index_first_right_closet	= a_net_line.indexOf( ">" );
		
		ref	= a_net_line.substring( index_first_quota + 1, index_first_right_closet - 1 );

		return ref;
	}

	//@param a_net_line <source ref="acm647341">Proceedings of the 1998 IEEE Symposium Information Visualization</source>
	private String find_source( String a_net_line ){
		String ref	 = new String();

		int 
			index_first_quota			= a_net_line.indexOf( "\"" ),
			index_first_right_closet	= a_net_line.indexOf( ">" );
		
		ref	= a_net_line.substring( index_first_quota + 1, index_first_right_closet - 1 );

		return ref;
	}

	private boolean is_infovis_source( String a_source ){
		String[] sources	= IEEE_Infovis_Paper.INFOVIS_REF;
		for ( int i = 0; i < sources.length; i++ ){
			if ( a_source.equals( sources[i] ) ){
				return true;
			}
		}

		return false;
	}
}